package cm

import (
	"crypto/ecdsa"
	crand "crypto/rand"
	"encoding/hex"
	"math/big"

	"gitee.com/law-api/log"

	"github.com/PicoChain/crypto"
)

//freeToken represent a new account get free token to call contract
func freeToken() *big.Int {
	var baseToken = new(big.Int).SetUint64(1e18)
	var callTime = new(big.Int).SetUint64(10)

	token := new(big.Int).Mul(baseToken, callTime)
	return token
}

//GenerateAccount generate a pair of keys,and tranfer 1 eth for its account
func (cm *ClientManager) GenerateAccount() (string, string, string, error) {
	return cm.generateAccount()
}

func (cm *ClientManager) generateAccount() (string, string, string, error) {
	var rand = crand.Reader
	//create a new accounts from S256 ponit
	key, err := ecdsa.GenerateKey(crypto.S256(), rand)
	if err != nil {
		log.Warn("genearte key", "err", err)
		return "", "", "", ErrAccInit
	}
	addr := crypto.PubkeyToAddress(key.PublicKey)
	pubs := hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))
	privs := hex.EncodeToString(crypto.FromECDSA(key))

	//allow account to alive in picoChain
	url, c := cm.randomClient()

	cm.keyLock.Lock()
	defer cm.keyLock.Unlock()

	//accord pool account nonce,transfer token to new accout
	nonce, err := cm.GetUserNonce(cm.keyAcc.From)
	if err != nil {
		log.Warn("keyAcc nonce loading failed")
		return "", "", "", ErrAccInit
	}

	//transfer to picoChain
	tx, err := transfer(cm.keyAcc, addr, freeToken(), nonce, c)
	if err != nil {
		log.Warn("keyAcc tranfer", "err", err)
		return "", "", "", ErrAccInit
	}
	log.Info("new account", "Number", nonce, "target:", url, "txhash", tx.Hash().Hex())

	//update nonce
	nonce++
	cm.SetUserNonce(cm.keyAcc.From, nonce)

	return addr.Hex(), pubs, privs, nil
}
